/**
 * 
 */
package systole.view.crud.controller;

import javax.swing.JDialog;
import systole.exceptions.ExceptionDAO;

import systole.persistence.FacadeDB;
import systole.view.SystoleApp;
import systole.view.abstractController.AbstractEditViewController;
import systole.view.utils.ErrorDialog;

/**
 * @author jmj
 * 
 */
public abstract class ControllerEntityEdition extends AbstractEditViewController {

    private boolean changesCommitted;
    private boolean editing;
    /**
     * Entity name
     */
    protected String entityName;
    /**
     * Facade to access DB
     */
    protected FacadeDB facadeDB;
    /**
     * Form to edit the entity
     */
    protected JDialog editForm;
    /**
     * Entity selected
     */
    protected Object curretnEntity = null;
    /**
     * description for new operation
     * Child controller can change by gender
     */
    protected String newDescription = "Nuevo";
    /**
     * description for edition operation
     * Child controller can change by gender
     */
    protected String editDescription = "Editar";

    /**
     *
     */
    public ControllerEntityEdition() {
        super();
        this.facadeDB = FacadeDB.getInstance();
        this.changesCommitted = false;
    }

    /**
     * @param editing
     *            the editing to set
     */
    protected void setEditing(boolean editing) {
        this.editing = editing;
    }

    /**
     * @return the editing
     */
    protected boolean isEditing() {
        return this.editing;
    }

    /**
     * method to confirm operation
     */
    public void ok() {
        String msg = this.valid();
        if (msg == null) {
            try {
                this.loadEntityFromForm();
                this.setChangesCommitted(true);
                this.editForm.setVisible(false);
                this.editForm.dispose();
                this.save();
                this.facadeDB.commitTransaction();
            } catch (ExceptionDAO ex) {
                this.facadeDB.rollbackTransaction();
                ErrorDialog.showError(this.editForm, ex.getMessage());
            }
        } else {
            ErrorDialog.showError(this.editForm, msg);
        }
    }

    /**
     * method to cancel operation
     */
    public void cancel() {
        this.editForm.setVisible(false);
        this.facadeDB.rollbackTransaction();
        this.setChangesCommitted(false);
        this.editForm.dispose();
    }

    /**
     *
     * @param entity
     *            Entity to edit.
     */
    public void editEntity(Object entity) {
        this.facadeDB.startTransaction();
        this.setEditing(true);
        this.curretnEntity = entity;
        this.showForm(SystoleApp.getApplication().getMainFrame());
    }

    /**
     * method to create a new entity
     * @return return the new entity
     */
    public Object newEntity() {
        this.facadeDB.startTransaction();
        this.setEditing(false);
        this.showForm(SystoleApp.getApplication().getMainFrame());
        return (this.isChangesCommitted() ? this.curretnEntity : null);

    }

    /**
     * Method to add the current entity in edit form
     */
    protected abstract void loadEntityOnForm();

    /**
     * Method to load the entity edited from form.
     */
    protected abstract void loadEntityFromForm();

    /**
     * @return if the entity edited is valid
     */
    protected abstract String valid();

    /**
     * Method to show the edit form 
     * 
     * @param parent
     */
    protected void showForm(java.awt.Frame parent) {
        try {
            if (!this.isEditing()) {
                this.curretnEntity = this.createEntity();
            }

            this.editForm = this.createEditionForm(parent);
            this.initFormsControls();

            if (this.isEditing()) {
                this.editForm.setTitle(this.editDescription + " " + this.entityName);
                this.loadEntityOnForm();
            } else {
                this.editForm.setTitle(this.newDescription + " " + this.entityName);
            }
            this.editForm.setLocationRelativeTo(parent);
            this.setCloseListener(this.editForm);
            this.loadIconOnForm();
            this.editForm.setVisible(true);
        } catch (ExceptionDAO ex) {
            this.facadeDB.refreshSession();
            ErrorDialog.showError(this.editForm, ex.getMessage());
        }
    }

    /**
     * Method to save changes
     * @throws ExceptionDAO 
     */
    protected abstract void save() throws ExceptionDAO;

    /**
     * @return the changesCommitted
     */
    protected boolean isChangesCommitted() {
        return this.changesCommitted;
    }

    /**
     * @param changesCommitted the changesCommitted to set
     */
    protected void setChangesCommitted(boolean changesCommitted) {
        this.changesCommitted = changesCommitted;
    }

    protected abstract void loadIconOnForm();

    protected abstract Object createEntity() throws ExceptionDAO;

    protected abstract JDialog createEditionForm(java.awt.Frame parent);

    protected void initFormsControls() throws ExceptionDAO {
        // emtpy for controller that not load any
    }
}
